package com.hypo.third.handler;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.util.ObjectUtils;
import java.lang.reflect.Field;
/**
 * @author shenkunlin
 */
public class WrapperParse {

    /**
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper<?> queryGL(Object instance, String minProName, boolean minIsEq, String maxProName, boolean maxIsEq) {
        //1、获取Class
        Class<?> clazz = instance.getClass();
        QueryWrapper<Object> query = new QueryWrapper<>();

        //2、构建查询条件
        try {
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                //2.1 暴力破解
                field.setAccessible(true);
                //2.2 获取名字
                String name = field.getName();
                if ("serialVersionUID".equals(name)) {
                    continue;
                }

                //2.3 获取字段类型
                String clazzName = field.getType().getName();
                //2.4 String则拼接like
                if ("java.lang.String".equals(clazzName)) {
                    stringMatch(instance, query, field, name, name);
                } else if (isSupportedType(clazzName)) {
                    if (!ObjectUtils.isEmpty(minProName) && name.equals(minProName)) {
                        if (minIsEq) {
                            query.ge(name, field.get(instance));
                        } else {
                            query.gt(name, field.get(instance));
                        }
                    } else if (!ObjectUtils.isEmpty(maxProName) && name.equals(maxProName)) {
                        if (maxIsEq) {
                            query.le(name, field.get(instance));
                        } else {
                            query.lt(name, field.get(instance));
                        }
                    } else {
                        reDateMatch(instance, query, field, name);
                    }
                } else {
                    reDateMatch(instance, query, field, name);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return query;
    }

    /**
     * 判断是否为支持的类型
     */
    private static boolean isSupportedType(String clazzName) {
        return "java.util.Date".equals(clazzName) ||
                "java.time.LocalDateTime".equals(clazzName) ||
                "java.time.LocalDate".equals(clazzName) ||
                "java.lang.Double".equals(clazzName) ||
                "java.lang.Integer".equals(clazzName) ||
                "java.lang.Long".equals(clazzName) ||
                "java.lang.Float".equals(clazzName) ||
                "java.lang.Short".equals(clazzName);
    }

    /**
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper<?> query(Object instance) {
        return queryGL(instance, null, false, null, false);
    }

    /**
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper<?> query(Object instance, String minProName) {
        return queryGL(instance, minProName, false, null, false);
    }

    /**
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper<?> query(Object instance, String minProName, String maxProName) {
        return queryGL(instance, minProName, false, maxProName, false);
    }

    /**
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper<?> queryMinEq(Object instance, String minProName, Boolean isEq) {
        return queryGL(instance, minProName, isEq != null && isEq, null, false);
    }

    /**
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper<?> queryMaxEq(Object instance, String maxProName, Boolean isEq) {
        return queryGL(instance, null, false, maxProName, isEq != null && isEq);
    }

    /**
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper<?> queryBetween(Object instance, String minProName, Boolean minIsEq, String maxProName, Boolean maxIsEq) {
        return queryGL(instance, minProName, minIsEq != null && minIsEq, maxProName, maxIsEq != null && maxIsEq);
    }

    /**
     * 非日期类型匹配
     */
    public static void reDateMatch(Object instance, QueryWrapper<Object> query, Field field, String columnName) {
        try {
            Object value = field.get(instance);
            // 获取@TableField注解中的value值
            columnName = getColumnName(field, columnName);
            if (ObjectUtils.isEmpty(columnName)) {
                return;
            }
            query.eq(!ObjectUtils.isEmpty(value), columnName, value);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 字符串匹配，这里包含了like查找
     */
    public static void stringMatch(Object instance, QueryWrapper<Object> query, Field field, String name, String columnName) {
        try {
            String value = (String) field.get(instance);
            // 获取@TableField注解中的value值  排除非数据库字段和逻辑删除字段
            columnName = getColumnName(field, columnName);
            if (ObjectUtils.isEmpty(columnName)) {
                return;
            }

            // 如果name中带有特定关键字，则用like组装，否则用eq组装
            if (name.toLowerCase().contains("orderno") ||
                    name.toLowerCase().contains("key") ||
                    name.toLowerCase().contains("name") ||
                    name.toLowerCase().contains("title") ||
                    name.toLowerCase().contains("desc") ||
                    name.toLowerCase().contains("email")) {
                query.like(!ObjectUtils.isEmpty(value), columnName, value);
            } else {
                query.eq(!ObjectUtils.isEmpty(value), columnName, value);
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析字段名字
     */
    public static String getColumnName(Field field, String columnName) {
        TableField tableField = field.getAnnotation(TableField.class);

        //如果是逻辑删除字段，或者数据库不存在的字段，则不进行查询
        if (field.getAnnotation(TableLogic.class) != null || (tableField != null && !tableField.exist())) {
            return null;
        }
        //从主键或者非主键获取字段名字
        TableId tableId = field.getAnnotation(TableId.class);
        if (tableField != null && !ObjectUtils.isEmpty(tableField.value())) {
            columnName = tableField.value();
        } else if (tableId != null && !ObjectUtils.isEmpty(tableId.value())) {
            columnName = tableId.value();
        }
        columnName = StringUtils.camelToUnderline(columnName);
        return columnName;
    }
}
